const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"]
  },
  transports: ['websocket']
});

const appId = '67ce83a323de86148ae30cd8'
const collectionId = '67ce3c7446a326209813c99b'
const apiKey = 'fastgpt-pmZdkSgNEoFbxMgBJcqHFw08Z4lnuyEQ29NVnWatwK6nEcpcrCNZENWq1'
let flag = false // 有转人工字样以后变成true，以后都走客服
const userActiveRooms = new Map(); // 用于追踪用户当前的活跃房间 Map<userId, roomId>
const kefuActiveRooms = new Map(); // 用于追踪客服当前的活跃房间 Map<kefuName, Set<roomId>>

// Socket.IO连接处理
io.on('connection', (socket) => {
  console.log(`客户端连接成功 ID: ${socket.id}`);
 
  socket.on('message', async (data, callback) => {
    try {
      console.log('收到消息:', data);
      
      // 首先检查消息内容是否为空
      if (!data.content) {
        callback({ 
          status: 'error', 
          message: '消息内容不能为空'
        });
        return;
      }

      // 处理转人工请求
      if (data.isChange && data.content.startsWith('转人工')) {
        flag = true;
        
        // 获取目标客服名称
        const targetKefu = data.content.substring(3);
        
        // 检查目标客服是否存在且在线
        const kefuSockets = Array.from(io.sockets.sockets.values()).filter(s => 
          s.handshake.query.username?.startsWith('客') && 
          s.handshake.query.username === targetKefu
        );

        if (kefuSockets.length === 0) {
          callback({ 
            status: 'error', 
            message: '目标客服不存在或不在线' 
          });
          return;
        }

        // 生成新房间ID
        const newRoomId = `room_${data.userId}_${Date.now()}`;
        
        // 如果是客服发起的转接
        if (data.username.startsWith('客')) {
          const oldRoomId = data.roomId;
          const currentRoom = io.sockets.adapter.rooms.get(oldRoomId);
          
          if (currentRoom) {
            // 找到当前房间内的用户
            for (const socketId of currentRoom) {
              const clientSocket = io.sockets.sockets.get(socketId);
              if (clientSocket) {
                const clientUsername = clientSocket.handshake.query.username;
                
                // 如果是用户（非客服），则转移到新房间
                if (!clientUsername?.startsWith('客')) {
                  // 更新用户的活跃房间
                  userActiveRooms.set(clientSocket.handshake.query.userId, newRoomId);
                  
                  // 让用户离开旧房间，加入新房间
                  clientSocket.leave(oldRoomId);
                  clientSocket.join(newRoomId);
                  clientSocket.roomId = newRoomId;
                } else {
                  // 如果是客服，从旧房间移除
                  clientSocket.leave(oldRoomId);
                  // 更新客服的活跃房间列表
                  const kefuRooms = kefuActiveRooms.get(clientUsername) || new Set();
                  kefuRooms.delete(oldRoomId);
                  kefuActiveRooms.set(clientUsername, kefuRooms);
                }
              }
            }
          }

          // 更新原客服的房间信息
          const oldKefuRooms = kefuActiveRooms.get(data.username) || new Set();
          oldKefuRooms.delete(oldRoomId);
          kefuActiveRooms.set(data.username, oldKefuRooms);

          // 更新新客服的房间信息
          const newKefuRooms = kefuActiveRooms.get(targetKefu) || new Set();
          newKefuRooms.add(newRoomId);
          kefuActiveRooms.set(targetKefu, newKefuRooms);

          // 发送系统消息到新房间
          io.to(newRoomId).emit('message', {
            id: crypto.randomUUID(),
            text: `${data.username} 将您转接至${targetKefu}`,
            userId: 'system',
            username: '系统',
            timestamp: new Date().toISOString(),
            roomId: newRoomId
          });
        } else {
          // 用户发起的转人工请求
          socket.join(newRoomId);
          userActiveRooms.set(data.userId, newRoomId);
          
          // 更新新客服的房间信息
          const kefuRooms = kefuActiveRooms.get(targetKefu) || new Set();
          kefuRooms.add(newRoomId);
          kefuActiveRooms.set(targetKefu, kefuRooms);
        }

        // 向目标客服发送会话信息
        io.to(kefuSockets[0].id).emit('session', {
          roomId: newRoomId,
          kefu: targetKefu,
          userId: data.userId,
          username: data.username,
          timestamp: new Date().toISOString(),
          previousKefu: data.username.startsWith('客') ? data.username : undefined
        });

        // 保存新房间ID到socket实例
        socket.roomId = newRoomId;

        callback({ 
          status: 'success',
          roomId: newRoomId
        });
        return;
      }

      // 处理客服消息
      if (data.username.startsWith('客')) {
        // 如果是客服，检查他们是否有权限访问该房间
        const kefuRooms = kefuActiveRooms.get(data.username);
        if (!kefuRooms || !kefuRooms.has(data.roomId)) {
          callback({ 
            status: 'error', 
            message: '您不再是该会话的活跃客服' 
          });
          return;
        }
        
        // 构造消息对象
        const messageObj = {
          id: crypto.randomUUID(),
          text: data.content,
          userId: data.userId,
          username: data.username,
          timestamp: new Date().toISOString(),
          roomId: data.roomId
        };

        // 发送到房间
        io.to(data.roomId).emit('message', messageObj);
        callback({ status: 'success' });
        return;
      }

      // 处理用户消息
      if (flag) {
        // 人工模式
        const roomId = userActiveRooms.get(data.userId);
        if (!roomId) {
          callback({ 
            status: 'error', 
            message: '未找到有效的房间ID，请重新连接客服' 
          });
          return;
        }

        const messageObj = {
          id: crypto.randomUUID(),
          text: data.content,
          userId: data.userId,
          username: data.username,
          timestamp: new Date().toISOString(),
          roomId: roomId
        };

        io.to(roomId).emit('message', messageObj);
        callback({ status: 'success' });
        return;
      }

      // AI 模式（非人工模式）
      const userMessage = {
        id: crypto.randomUUID(),
        text: data.content,
        userId: data.userId,
        username: data.username,
        timestamp: new Date().toISOString()
      };
      socket.emit('message', userMessage);
      callback({ status: 'success' });

      try {
        const aiResponse = await askAI(data.content, data.userId);
        const aiMessage = {
          id: crypto.randomUUID(),
          text: aiResponse.choices[0].message.content,
          userId: 'AI',
          username: 'AI助手',
          timestamp: new Date().toISOString()
        };
        socket.emit('aiMessage', aiMessage);
      } catch (err) {
        console.error('AI响应错误:', err);
        socket.emit('message', {
          id: crypto.randomUUID(),
          text: 'AI服务暂时不可用，请稍后再试',
          userId: 'system',
          username: '系统',
          timestamp: new Date().toISOString()
        });
      }

    } catch (err) {
      console.error('消息处理错误:', err);
      callback({ 
        status: 'error',
        message: err.message || '消息处理失败'
      });
    }
  });

  socket.on('joinRoom', (data) => {
    try {
      console.log('用户加入房间:', data);
      
      if (!data.roomId || !data.username) {
        console.error('加入房间失败: 缺少必要参数');
        return;
      }

      // 更新房间追踪信息
      if (data.username.startsWith('客')) {
        const kefuRooms = kefuActiveRooms.get(data.username) || new Set();
        kefuRooms.add(data.roomId);
        kefuActiveRooms.set(data.username, kefuRooms);
      } else {
        userActiveRooms.set(data.userId, data.roomId);
      }

      socket.join(data.roomId);
      socket.roomId = data.roomId;
      
      io.to(data.roomId).emit('message', {
        id: crypto.randomUUID(),
        text: `${data.username} 已加入房间`,
        userId: 'system',
        username: '系统',
        timestamp: new Date().toISOString(),
        roomId: data.roomId
      });

    } catch (err) {
      console.error('加入房间失败:', err);
    }
  });

  socket.on('leaveRoom', (data) => {
    try {
      console.log('用户离开房间:', data);
      socket.leave(data.roomId);
    } catch (err) {
      console.error('离开房间失败:', err);
    }
  });

  socket.on('editMessage', async data => {
    console.log('收到编辑消息:', data);
    console.log(data.originalQuestion, data.modifiedAnswer);
    try {
      // 查找知识库有没有该问题
      const res = await getDatasetData(data.originalQuestion, collectionId)
      console.log(111);
      if (res.data.list.length > 0) {
        const dataId = res.data.list[0]._id
        const response = await updateDatasetData(dataId, data.originalQuestion, data.modifiedAnswer)
        if (response.code === 200) {
          socket.emit('messageUpdate', '已更新')
        } else {
          socket.emit('messageUpdate', '更新失败，请稍后重试！')
        }
      } else {
        const r = await addDatasetData({
          q: data.originalQuestion,
          a: data.modifiedAnswer
        })
        if (r.data.insertLen === 1 && r.data.error.length === 0) {
          socket.emit('messageAdd', '已添加')
        } else {
          socket.emit('messageAdd', '添加失败，请稍后重试！')
        }
      }
    } catch(err) {
      console.log(err);
    }
  })

  // 用户评价
  socket.on('evaluate', async (data) => {
    console.log(data);
    try {
      const res = await getConversationHistoryById(data.chatId)
      console.log(res);
      const i = res.data.total - 1
      console.log(i);
      const dataId = res.data.list[i].dataId
      console.log(dataId);
      console.log(data.chatId);
      const response = await updateFeedback(data.chatId, dataId, data.text)
      console.log(response)
      if (response.code === 200) {
        socket.emit('evaluate', '评价成功')
      } else {
        socket.emit('evaluate', '评价失败，请稍后重试！')
      }
    } catch(err) {
      console.log(err);
    }
  });

  socket.on('disconnect', () => {
    console.log('客户端断开连接:', socket.id);
    
    const username = socket.handshake.query.username;
    const userId = socket.handshake.query.userId;

    // 清理房间追踪信息
    if (username?.startsWith('客')) {
      kefuActiveRooms.delete(username);
    } else if (userId) {
      userActiveRooms.delete(userId);
    }

    if (socket.roomId) {
      io.to(socket.roomId).emit('message', {
        id: crypto.randomUUID(),
        text: '对方已断开连接',
        userId: 'system',
        username: '系统',
        timestamp: new Date().toISOString()
      });
    }
  });

  socket.on('error', (err) => {
    console.error(`客户端错误 ${socket.id}:`, err.message);
  });
});

// 对话
async function askAI(question, chatId) {
  const response = await fetch('https://cloud.fastgpt.cn/api/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      chatId: chatId,
      variables: {
        uid: "asdfadsfasfd2323",
        name: "张三"
      },
      messages: [{ role: "user", content: question }]
    })
  });

  // 检查响应是否成功
  if (!response.ok) {
    throw new Error(`HTTP error! Status: ${response.status}`);
  }
 
  // 解析 JSON 数据
  const data = await response.json();
  return data;
}

// 获取集合的数据
async function getDatasetData(question, collectionId) {
  const response = await fetch('https://cloud.fastgpt.cn/api/core/dataset/data/v2/list', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      offset: 0,
      pagesize: 10,
      collectionId: collectionId,
      searchText: question
    })
  });
  return response.json();
}

// 添加数据
async function addDatasetData(data) {
  const response = await fetch('https://cloud.fastgpt.cn/api/core/dataset/data/pushData', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      collectionId: '67ce3c7446a326209813c99b',
      trainingType: 'qa',
      data: [ data ]
    })
  })
  return response.json();
}

// 修改接口
async function updateDatasetData(id, question, answer) {
  const response = await fetch('https://cloud.fastgpt.cn/api/core/dataset/data/update', {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      dataId: id,
      q: question,
      a: answer
    })
  });
  return response.json();
}

// 获取对话的历史记录
async function getConversationHistoryById(chatId) {
  const res = await fetch('https://cloud.fastgpt.cn/api/core/chat/getPaginationRecords', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      appId: appId,
      chatId: chatId,
      offset: 0,
      pageSize: 10,
      loadCustomFeedbacks: true
    })
  })
  return res.json();
}

// 赞/踩接口
async function updateFeedback(chatId, dataId, text) {
  const response = await fetch('https://cloud.fastgpt.cn/api/core/chat/feedback/updateUserFeedback', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      appId: appId,
      chatId: chatId,
      dataId: dataId,
      userGoodFeedback: text
    })
  })
  return response.json();
}

// 根路由处理
app.get('/', (req, res) => {
  res.json({
    status: 'ok',
    message: '聊天服务器正在运行',
    endpoints: {
      health: '/health',
      websocket: 'ws://localhost:3001'
    }
  });
});

// 健康检查路由
app.get('/health', (req, res) => {
  res.json({ 
    status: 'ok', 
    timestamp: new Date().toISOString(),
    connections: io.engine.clientsCount
  });
});

// 统一错误处理
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ 
    error: '服务端错误',
    message: err.message 
  });
});

http.listen(3001, () => {
  console.log('服务器启动在 http://localhost:3001');
});
